﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Data.Entity.Validation;
using System.Diagnostics;
using System.Linq;
using System.Web;
using WebMatrix.WebData;

namespace Board.Models
{
    public class WebUser
    {
        #region private variables 

        private t_UserProfile _userProfile = null;
        private HashSet<t_webpages_Roles> _roles = null; 
        private HashSet<Site> _accessibleSites = null;
        private HashSet<Unit> _accessibleUnits = null;
        private HashSet<Bed> _accessibleBeds = null;

        private HashSet<t_UnitBedPermission> _permissions = null; 


        #endregion

#region public static variables

        public static string USER_TYPE_NURSE = "Nurse";
        public static string USER_TYPE_DOCTOR = "Doctor";
        public static string USER_TYPE_SYSTEM = "System";

        public static int DEFAULT_RECORDS_PER_PAGE = 20;


#endregion

        #region public property


        public bool HasWebAccess
        {
            get
            {
                return _userProfile != null && !string.IsNullOrEmpty(_userProfile.UserName) && _roles != null &&
                       _roles.Count > 0 && DefaultSite != null && !string.IsNullOrEmpty(DefaultSite.SiteId);
            }
        }

        public bool HasProfile
        {
            get { return UserProfile != null; }
        }

        public t_UserProfile UserProfile
        {
            get { return _userProfile; } 
            set
            {
                _userProfile = value;
            }
        }

        public string Username
        {
            get
            {
                if (HasProfile)
                {
                    return UserProfile.UserName;
                }
                return "";
            }
            set { 
                if (HasProfile)
                {
                    UserProfile.UserName = value;
                }
                else
                {
                    UserProfile = new t_UserProfile();
                    UserProfile.UserName = value;
                }
            }
        }

        public int UserId
        {
            get {
                if (HasProfile) return UserProfile.UserId;
                return 0;
            }
        }

        public string FirstName
        {
            get
            {
                if (HasProfile) return UserProfile.FirstName;
                return "";
            }
            set
            {
                if (HasProfile)
                {
                    UserProfile.FirstName = value;
                }
                else
                {
                    UserProfile = new t_UserProfile();
                    UserProfile.FirstName = value;
                }
            }
        }

        public string LastName
        {
            get
            {
                if (HasProfile) return UserProfile.LastName;
                return "";
            }
            set
            {
                if (HasProfile)
                {
                    UserProfile.LastName = value;
                }
                else
                {
                    UserProfile = new t_UserProfile();
                    UserProfile.LastName = value;
                }
            }
        }
        
        public string FullName
        {
            get
            {
                if (HasProfile) return UserProfile.FirstName + " " + UserProfile.LastName;
                return "";
            }
        }

        public string UserType
        {
            get { if (HasProfile) return UserProfile.UserType;
                return "";
            }
            set
            {
                if (HasProfile)
                {
                    UserProfile.UserType = value;
                }
                else
                {
                    UserProfile = new t_UserProfile();
                    UserProfile.UserType = value;
                }
            }
        }

        public DateTime CreationDate
        {
            get
            {
                if (HasProfile) return UserProfile.CreationDate.HasValue?UserProfile.CreationDate.Value:DateTime.Now;
                return DateTime.Now;
            }
            set { _userProfile.CreationDate = value; }
        }

        public bool ShowAllBed
        {
            get { if (HasProfile) return UserProfile.ShowAllBeds.HasValue && UserProfile.ShowAllBeds.Value;
                return false;
            }
            set
            {
                if (HasProfile)
                {
                    UserProfile.ShowAllBeds = value;
                }
                else
                {
                    UserProfile = new t_UserProfile();
                    UserProfile.ShowAllBeds = value;
                }
            }
        }

        public int CreatedBy
        {
            get
            {
                if (HasProfile && _userProfile.CreatedBy.HasValue) return _userProfile.CreatedBy.Value;
                return 0;
            }
            set
            {
                if (HasProfile)
                {
                    _userProfile.CreatedBy = value;
                }
                else
                {
                    _userProfile = new t_UserProfile();
                    _userProfile.CreatedBy = value;
                }
            }
        }

        public Site DefaultSite
        {
            get
            {
                Site site = new Site();
                if (HasProfile && !string.IsNullOrEmpty(_userProfile.DefaultSite) )
                {
                    if (AccessibleSites.Any(s => s.SiteId.Equals(_userProfile.DefaultSite)))
                    {
                        site = AccessibleSites.FirstOrDefault(s => s.SiteId.Equals(_userProfile.DefaultSite));
                    }else
                    {
                        site = new Site(_userProfile.DefaultSite);
                    }
                }
                return site;
            }
            set
            {
                if (HasProfile )
                {
                    if (value != null)
                    {
                        _userProfile.DefaultSite = value.SiteId;
                    }
                }
            }
        }

        public Unit DefaultUnit
        {
            get
            {
                if (HasProfile && !string.IsNullOrEmpty(_userProfile.DefaultSite) && !string.IsNullOrEmpty(_userProfile.DefaultUnit))
                {
                    return new Unit(_userProfile.DefaultSite, _userProfile.DefaultUnit);
                }
                return new Unit();
            }
            set
            {
                if (HasProfile)
                {
                    if (value != null)
                    {
                        _userProfile.DefaultSite = value.SiteId;
                        _userProfile.DefaultUnit = value.UnitId;
                    }
                    else
                    {
                        _userProfile.DefaultUnit = null;
                    }
                }
            }
        }

        public int DefaultRecordsPerPage
        {
            get
            {
                if (HasProfile && _userProfile.DefaultRecordsPerPage.HasValue && _userProfile.DefaultRecordsPerPage>1)
                {
                    return _userProfile.DefaultRecordsPerPage.Value;
                }
                return 50;
            }
            set
            {
                if (value > 1)
                {
                    _userProfile.DefaultRecordsPerPage = value;
                }
            }
        }

        public HashSet<Role> Roles
        {
            get
            {
                if (HasProfile && _roles==null)
                {
                    if (_userProfile.webpages_Roles != null)
                    {
                        _roles = new HashSet<t_webpages_Roles>(_userProfile.webpages_Roles);
                    }
                    else
                    {
                        using (DbEntities db = new DbEntities())
                        {
                            _roles = new HashSet<t_webpages_Roles>(db.t_UserProfile.FirstOrDefault(u => u.UserId == UserId).webpages_Roles);
                        }
                    }
                }
                return new HashSet<Role>(_roles.Select(r => new Role(r)));
            }
            set { _roles = new HashSet<t_webpages_Roles>(value.Select(v=>v.WebpagesRoles)); }
        }

        public HashSet<t_UnitBedPermission> Permissions
        {
            get
            {
                if (_permissions == null)
                {
                    if (HasProfile && _userProfile.UserId > 0)
                    {
                        using (DbEntities db = new DbEntities())
                        {
                            _permissions = new HashSet<t_UnitBedPermission>(from p in db.t_UnitBedPermission where p.UserId == UserId select p);
                        }
                    }
                    else
                    {
                        _permissions = new HashSet<t_UnitBedPermission>();
                    }
                }
                return _permissions;
            }
        } 

        public bool IsAdmin
        {
            get
            {
                return HasProfile && UserProfile.webpages_Roles != null &&
                       _roles.Any(r => r.RoleName.Equals(Role.ROLE_ADMIN));
            }
        }

        public bool IsSiteAdmin
        {
            get
            {
                return HasProfile && UserProfile.webpages_Roles != null &&
                       _roles.Any(r => r.RoleName.Equals(Role.ROLE_SITE_ADMIN));
            }
        }

        public bool IsUnitAdmin
        {
            get
            {
                return HasProfile && UserProfile.webpages_Roles != null &&
                       _roles.Any(r => r.RoleName.Equals(Role.ROLE_UNIT_ADMIN));
            }
        }

        public bool IsKardexUser
        {
            get
            {
                return HasProfile && UserProfile.webpages_Roles != null &&
                       _roles.Any(r => r.RoleName.Equals(Role.ROLE_KARDEX_USER));
            }
        }

        public bool HasSomeAdminPermission
        {
            get
            {
                return HasProfile && UserProfile.webpages_Roles != null &&
                       _roles.Any(r => Role.AdminRoleNames.Contains(r.RoleName));
            }
        }

        public static List<string> AllUserTypes
        {
            get
            {
                return new List<string>(){ USER_TYPE_SYSTEM, USER_TYPE_DOCTOR, USER_TYPE_NURSE};
            }
        } 


        public HashSet<Site> AccessibleSites
        {
            get
            {
                if (HasProfile && UserProfile.UserId>0)
                {
                    if (_accessibleSites == null)
                    {
                        using (DbEntities db = new DbEntities())
                        {
                            var beds = from b in db.t_AllUnitBed
                                       orderby b.SiteID, b.UnitID, b.Bed
                                           select b;
                            if (IsAdmin)
                            {
                                
                                if (beds.Any())
                                {
                                    _accessibleBeds = new HashSet<Bed>(beds.Select(b=>new Bed(){SiteId = b.SiteID, UnitId=b.UnitID, BedId=b.Bed, BedStatus = b.BedStatus, BedType = b.BedType, BoardId = b.BoardId}));
                                    _accessibleUnits = new HashSet<Unit>(beds.Select(b => new { b.SiteID, b.UnitID }).Distinct().Select(u => new Unit() { SiteId = u.SiteID, UnitId = u.UnitID }));
                                    foreach (Unit unit in _accessibleUnits)
                                    {
                                        unit.AccessibleBeds = new HashSet<Bed>(_accessibleBeds.Where(b => b.SiteId.Equals(unit.SiteId) && b.UnitId.Equals(unit.UnitId)));
                                    }

                                    _accessibleSites = new HashSet<Site>(_accessibleUnits.Select(u => u.SiteId).Distinct().Select(s => new Site(s)));
                                    foreach (Site site in _accessibleSites)
                                    {
                                        site.AccessibleUnit = new HashSet<Unit>(_accessibleUnits.Where(u => u.SiteId.Equals(site.SiteId)));
                                    }
                                }
                            }
                            else
                            {
                                _accessibleSites = new HashSet<Site>();
                                _accessibleUnits = new HashSet<Unit>();
                                _accessibleBeds = new HashSet<Bed>();
                                var accessibleBeds = from b in db.t_UnitBedPermission
                                                     where b.UserId == _userProfile.UserId
                                                     orderby b.SiteID, b.UnitID, b.Bed
                                                     select b;
                                if (accessibleBeds.Any())
                                {
                                    if (IsSiteAdmin)
                                    {
                                        _accessibleBeds.UnionWith(new HashSet<Bed>(beds.Where(b => b.SiteID.Equals(DefaultSite.SiteId)).Select(b => new Bed() { SiteId = b.SiteID, UnitId = b.UnitID, BedId = b.Bed, BedStatus = b.BedStatus, BedType = b.BedType, BoardId = b.BoardId })));
                                        _accessibleUnits.UnionWith(new HashSet<Unit>(_accessibleBeds.Select(b => new { b.SiteId, b.UnitId }).Distinct().Select(u => new Unit() { SiteId = u.SiteId, UnitId = u.UnitId })));
                                        foreach (var accessibleUnit in _accessibleUnits)
                                        {
                                            accessibleUnit.AccessibleBeds = new HashSet<Bed>(_accessibleBeds.Where(b => b.SiteId.Equals(accessibleUnit.SiteId) && b.UnitId.Equals(accessibleUnit.UnitId)));
                                        }
                                        DefaultSite.AccessibleUnit = _accessibleUnits;
                                        _accessibleSites.Add(DefaultSite);
                                    }
                                    else if (IsUnitAdmin)
                                    {
                                        _accessibleBeds.UnionWith(new HashSet<Bed>(beds.Where(b => b.SiteID.Equals(DefaultUnit.SiteId) && b.UnitID.Equals(DefaultUnit.UnitId)).Select(b => new Bed() { SiteId = b.SiteID, UnitId = b.UnitID, BedId = b.Bed, BedStatus = b.BedStatus, BedType = b.BedType, BoardId = b.BoardId })));
                                        DefaultUnit.AccessibleBeds = _accessibleBeds;
                                        _accessibleUnits.Add(DefaultUnit);
                                        DefaultSite.AccessibleUnit = _accessibleUnits;
                                        _accessibleSites.Add(DefaultSite);
                                    }
                                    foreach (var tUnitBedPermission in accessibleBeds)
                                    {
                                        if (Unit.ALL_UNITS.Equals(tUnitBedPermission.UnitID) && !_accessibleSites.Any(s => s.SiteId.Equals(tUnitBedPermission.SiteID)))
                                        {
                                            var theBeds = new HashSet<Bed>(beds.Where(b => b.SiteID.Equals(tUnitBedPermission.SiteID)).Select(b => new Bed() { SiteId = b.SiteID, UnitId = b.UnitID, BedId = b.Bed, BedStatus = b.BedStatus, BedType = b.BedType, BoardId = b.BoardId }));
                                            _accessibleBeds.UnionWith(theBeds);
                                            var theUnits = new HashSet<Unit>(theBeds.Select(b => new { b.SiteId, b.UnitId }).Distinct().Select(u => new Unit() { SiteId = u.SiteId, UnitId = u.UnitId }));
                                            foreach (var theUnit in theUnits)
                                            {
                                                theUnit.AccessibleBeds = new HashSet<Bed>(theBeds.Where(b => b.UnitId.Equals(theUnit.UnitId)));
                                            }
                                            _accessibleUnits.UnionWith(theUnits);
                                            Site theSite = new Site(tUnitBedPermission.SiteID);
                                            theSite.AccessibleUnit = theUnits;
                                            _accessibleSites.Add(theSite);
                                        }
                                        else if (Bed.ALL_BEDS.Equals(tUnitBedPermission.Bed) &&
                                                 !_accessibleUnits.Any(
                                                     u =>
                                                     u.SiteId.Equals(tUnitBedPermission.SiteID) &&
                                                     u.UnitId.Equals(tUnitBedPermission.UnitID)))
                                        {
                                            var theBeds =
                                                new HashSet<Bed>(
                                                    beds.Where(
                                                        b =>
                                                        b.SiteID.Equals(tUnitBedPermission.SiteID) &&
                                                        b.UnitID.Equals(tUnitBedPermission.UnitID))
                                                        .Select(
                                                            b =>
                                                            new Bed()
                                                                {
                                                                    SiteId = b.SiteID,
                                                                    UnitId = b.UnitID,
                                                                    BedId = b.Bed,
                                                                    BedStatus = b.BedStatus,
                                                                    BedType = b.BedType
                                                                    ,
                                                                    BoardId = b.BoardId
                                                                }));
                                            _accessibleBeds.UnionWith(theBeds);
                                            var theUnit = new Unit(tUnitBedPermission.SiteID, tUnitBedPermission.UnitID);
                                            theUnit.AccessibleBeds = theBeds;
                                            _accessibleUnits.Add(theUnit);
                                            if (!_accessibleSites.Any(s => s.SiteId.Equals(tUnitBedPermission.SiteID)))
                                            {
                                                Site theSite = new Site(tUnitBedPermission.SiteID);
                                                theSite.AccessibleUnit = new HashSet<Unit>();
                                                _accessibleSites.Add(theSite);
                                            }
                                            _accessibleSites.FirstOrDefault(
                                                s => s.SiteId.Equals(tUnitBedPermission.SiteID))
                                                            .AccessibleUnit.Add(theUnit);
                                        }
                                        else if(!_accessibleBeds.Any(b=>b.SiteId.Equals(tUnitBedPermission.SiteID) && b.UnitId.Equals(tUnitBedPermission.UnitID) && b.BedId.Equals(tUnitBedPermission.Bed) ))
                                        {
                                            Bed theBed = new Bed(tUnitBedPermission.SiteID, tUnitBedPermission.UnitID, tUnitBedPermission.Bed);
                                            Unit theUnit = new Unit(tUnitBedPermission.SiteID, tUnitBedPermission.UnitID);
                                            if (
                                                !_accessibleUnits.Any(
                                                    u =>
                                                    u.SiteId.Equals(tUnitBedPermission.SiteID) &&
                                                    u.UnitId.Equals(tUnitBedPermission.UnitID)))
                                            {
                                                theUnit.AccessibleBeds = new HashSet<Bed>();
                                                _accessibleUnits.Add(theUnit);
                                            }
                                            else
                                            {
                                                theUnit = _accessibleUnits.FirstOrDefault(
                                                    u =>
                                                    u.SiteId.Equals(tUnitBedPermission.SiteID) &&
                                                    u.UnitId.Equals(tUnitBedPermission.UnitID));
                                            }
                                            theUnit.AccessibleBeds.Add(theBed);
                                            if (!_accessibleSites.Any(u =>u.SiteId.Equals(tUnitBedPermission.SiteID)))
                                            {
                                                Site theSite = new Site(tUnitBedPermission.SiteID);
                                                theSite.AccessibleUnit = new HashSet<Unit>();
                                            }
                                            _accessibleSites.FirstOrDefault(
                                                u => u.SiteId.Equals(tUnitBedPermission.SiteID))
                                                            .AccessibleUnit.Add(theUnit);
                                        }
                                    }
                                }
                            }
                            
                        }
                    }
                    return _accessibleSites;
                }
                return new HashSet<Site>();
            }
        }

        public HashSet<Unit> AccessibleUnits
        {
            get
            {
                if (HasProfile && UserProfile.UserId > 0 && AccessibleSites.Any() && _accessibleUnits.Any())
                {
                    return _accessibleUnits;
                }
                return new HashSet<Unit>();
            }
        }

        public HashSet<Bed> AccessibleBeds
        {
            get
            {
                if (HasProfile && UserProfile.UserId > 0 && AccessibleSites.Any() && _accessibleBeds.Any())
                {
                    return _accessibleBeds;
                }
                return new HashSet<Bed>();
            }
        } 

        public HashSet<WebUser>  AccessibleUsers
        {
            get
            {
                if (HasSomeAdminPermission)
                {
                    List<string> siteList = AccessibleSites.Select(s => s.SiteId).ToList();
                    List<string> unitList = AccessibleUnits.Select(s => s.UnitId).ToList();
                    using (DbEntities db = new DbEntities())
                    {
                        return new HashSet<WebUser>((from u in db.t_UserProfile
                                                    where Tools.CurrentUser.IsAdmin ||
                                                          (siteList.Contains(u.DefaultSite) &&
                                                           (!Tools.CurrentUser.IsUnitAdmin ||
                                                            unitList.Contains(u.DefaultUnit)))
                                                    orderby u.FirstName, u.LastName
                                                    select u).ToList().Select(u=>new WebUser(u, (HashSet<t_webpages_Roles>)u.webpages_Roles)).ToList());
                    }
                }
                return new HashSet<WebUser>(){this};
            }
        }


        public HashSet<Role> AccessibleRoles
        {
            get
            {
                HashSet<Role> roles = new HashSet<Role>();
                if (IsAdmin) roles.Add(Role.Admin);
                if (IsAdmin || IsSiteAdmin) roles.Add(Role.SiteAdmin);
                if (HasSomeAdminPermission) roles.Add(Role.UnitAdmin);
                if (HasSomeAdminPermission || IsUnitAdmin)
                {
                    roles.Add(Role.KardexUser);
                    roles.Add(Role.KardexViewer);
                }
                return roles;
            }
        } 

        #endregion



        #region constructors
        public WebUser(string username)
        {
            UserProfile = null;
            using (DbEntities db = new DbEntities())
            {
                var userProfiles = (from u in db.t_UserProfile
                                    where u.UserName.Equals(username)
                                    select u).ToList();
                if (userProfiles.Any())
                {
                    _userProfile = userProfiles.FirstOrDefault();
                    _roles = (HashSet<t_webpages_Roles>)(_userProfile.webpages_Roles);
                }
            }
        }

        public WebUser(int userId)
        {
            UserProfile = null;
            using (DbEntities db = new DbEntities())
            {
                var userProfiles = (from u in db.t_UserProfile
                                    where u.UserId == userId
                                    select u).ToList();
                if (userProfiles.Any())
                {
                    _userProfile = userProfiles.FirstOrDefault();
                    _roles = (HashSet<t_webpages_Roles>)(_userProfile.webpages_Roles);
                }
            }
        }

        public WebUser(string username, string firstName, string lastName, string userType, bool showAllBeds, string defaultSite, string defaultUnit, HashSet<t_webpages_Roles> roles )
        {
            _userProfile = new t_UserProfile();
            _userProfile.UserName = username;
            _userProfile.FirstName = firstName;
            _userProfile.LastName = lastName;
            _userProfile.CreatedBy = Tools.CurrentUser.UserId;
            _userProfile.UserType = userType;
            _userProfile.ShowAllBeds = showAllBeds;
            _userProfile.CreationDate = DateTime.Now;
            _userProfile.DefaultSite = string.IsNullOrEmpty(defaultSite) ? "HSC" : defaultSite;
            _userProfile.DefaultUnit = string.IsNullOrEmpty(defaultUnit) ? "CH4" : defaultUnit;
            _userProfile.CreatedBy = Tools.CurrentUser.UserId;
            _userProfile.webpages_Roles = roles;
            
        }

        public WebUser(t_UserProfile userProfile, HashSet<t_webpages_Roles> roles )
        {
            _roles = roles;
            UserProfile = userProfile;
       }

        public WebUser()
        {
        }

        #endregion




        public bool HaveAccessTo(WebUser user)
        {
            if (HasProfile && user.HasProfile)
            {
                if (_userProfile.UserId == (user.UserProfile.UserId)) return true;
                if (IsAdmin) return true;
                if (user.IsAdmin) return false;
                if (user.IsSiteAdmin && !IsSiteAdmin) return false;
                if (user.IsUnitAdmin && !HasSomeAdminPermission) return false;
                if (IsSiteAdmin && _userProfile.DefaultSite.Equals(user.UserProfile.DefaultSite)) return true;
                if (IsUnitAdmin && _userProfile.DefaultSite.Equals(user.UserProfile.DefaultSite) &&
                    _userProfile.DefaultUnit.Equals(user.UserProfile.DefaultUnit)) return true;
            }
            return false;
        }

        public bool HaveAccessTo(Site site)
        {
            return AccessibleSites.Any(s => s.SiteId.Equals(site.SiteId + ""));
        }

        public bool HaveAccessTo(Unit unit)
        {
            return AccessibleUnits.Any((s => s.SiteId.Equals(unit.SiteId + "") && s.UnitId.Equals(unit.UnitId + "")));
        }

        public bool HaveAccessTo(Bed bed)
        {
            return AccessibleBeds.Any((s => s.SiteId.Equals(bed.SiteId + "") && s.UnitId.Equals(bed.UnitId + "") && s.BedId.Equals(bed.BedId)));
        }

        public bool ResetPassword(string newPassword)
        {
            if (!HasProfile || string.IsNullOrEmpty(_userProfile.UserName) || _userProfile.UserId == 0 ||
                string.IsNullOrEmpty(newPassword)) return false;
            try
            {
                string token = WebSecurity.GeneratePasswordResetToken(_userProfile.UserName);
                return WebSecurity.ResetPassword(token, newPassword);
            }
            catch
            {
                
            }
            return false;
        }


        public void Save()
        {
            if (HasProfile)
            {
                if (UserProfile.UserId > 0)
                {
                    //existing record
                    using (DbEntities db = new DbEntities())
                    {
                        var userProfile = (from u in db.t_UserProfile
                                           where u.UserId == UserProfile.UserId
                                           select u).FirstOrDefault();
                        if (WebLog.LogValueChanged(db, "UserProfile", "FirstName", userProfile.FirstName,
                                                   UserProfile.FirstName))
                        {
                            userProfile.FirstName = UserProfile.FirstName;
                        }

                        if (WebLog.LogValueChanged(db, "UserProfile", "LastName", userProfile.LastName,
                                                   UserProfile.LastName))
                        {
                            userProfile.LastName = UserProfile.LastName;
                        }

                        if (WebLog.LogValueChanged(db, "UserProfile", "UserType", userProfile.UserType,
                                                   UserProfile.UserType))
                        {
                            userProfile.UserType = UserProfile.UserType;
                        }

                        if (WebLog.LogValueChanged(db, "UserProfile", "ShowAllBeds", userProfile.ShowAllBeds.ToString(),
                                                   UserProfile.ShowAllBeds.ToString()))
                        {
                            userProfile.ShowAllBeds = UserProfile.ShowAllBeds;
                        }

                        if (CreatedBy!=0 && WebLog.LogValueChanged(db, "UserProfile", "CreatedBy", userProfile.CreatedBy.ToString(),
                                                   UserProfile.CreatedBy.ToString()))
                        {
                            userProfile.CreatedBy = UserProfile.CreatedBy;
                        }

                        if ( WebLog.LogValueChanged(db, "UserProfile", "CreationDate", userProfile.CreatedBy.ToString(),
                                                   UserProfile.CreatedBy.ToString()))
                        {
                            userProfile.CreationDate = UserProfile.CreationDate;
                        }

                        if (WebLog.LogValueChanged(db, "UserProfile", "DefaultSite", userProfile.DefaultSite,
                                                   UserProfile.DefaultSite))
                        {
                            userProfile.DefaultSite = UserProfile.DefaultSite;
                        }

                        if (WebLog.LogValueChanged(db, "UserProfile", "DefaultUnit", userProfile.DefaultUnit,
                                                   UserProfile.DefaultUnit))
                        {
                            userProfile.DefaultUnit = UserProfile.DefaultUnit;
                        }

                        var allRoles = (from r in db.t_webpages_Roles
                                        select r).ToList();

                        foreach (var role in allRoles.Where(r=>Roles.Select(rl=>rl.RoleId).Contains(r.RoleId)))
                        {
                            if (!userProfile.webpages_Roles.Any(r => r.RoleId == role.RoleId))
                            {
                                userProfile.webpages_Roles.Add(role);
                                role.UserProfiles.Add(userProfile);
                            }
                        }
                        var roleIdsInDb = userProfile.webpages_Roles.Select(r => r.RoleId).ToList();
                        if(roleIdsInDb.Any())foreach (var id in roleIdsInDb)
                        {
                            if (!Roles.Any(r => r.RoleId == id))
                            {
                                var theRole = allRoles.FirstOrDefault(r => r.RoleId == id);
                                userProfile.webpages_Roles.Remove(theRole);
                                theRole.UserProfiles.Remove(userProfile);
                            }
                        }

                        //if (WebLog.LogValueChanged(db, "UserProfile", "webpages_role",
                        //                           string.Join(",",
                        //                                       userProfile.webpages_Roles.Select(r => r.RoleName)
                        //                                                   .ToList()),
                        //                           string.Join(",", _roles.Select(r => r.RoleName).ToList())))
                        //{
                        //    userProfile.webpages_Roles = _roles;
                        //}
                        
                        db.SaveChanges();
                        
                    }
                }
                else
                {
                    //new record
                    using (DbEntities db = new DbEntities())
                    {
                        db.t_UserProfile.Add(UserProfile);
                        db.SaveChanges();
                    }
                }

                

            }
        }

        public List<v_UserUnitPermission> GetShowBeds(bool showAll, string siteId, string unitId, string refreshMethod, int page, int recordsPerPage)
        {
            List<v_UserUnitPermission> result = new List<v_UserUnitPermission>();
            if (_userProfile == null) return result;
            if (showAll)
            {
                using (DbEntities db = new DbEntities())
                {
                    result.AddRange(db.v_UserUnitPermission.Where(u => u.UserId.Equals(_userProfile.UserId)).OrderBy(u=>u.SiteID).ThenBy(u=>u.UnitID).ThenBy(u=>u.Bed));
                }
            }
            else
            {
                using (DbEntities db = new DbEntities())
                {
                    var temp = (from u in db.v_UserUnitPermission
                                where u.UserId.Equals(_userProfile.UserId)
                                orderby u.SiteID, u.UnitID, u.Bed
                                select u).ToList();
                    if (temp.Any())
                    {
                        

                        if (string.IsNullOrEmpty(siteId) || !temp.Any(u=>u.SiteID.Equals(siteId)))
                        {
                            siteId = temp.FirstOrDefault().SiteID;
                            return temp.Where(u => u.SiteID.Equals(siteId)).ToList();
                        }
                        else if (string.IsNullOrEmpty(unitId) || !temp.Any(u=>u.UnitID.Equals(unitId)))
                        {
                            return temp.Where(u => u.SiteID.Equals(siteId)).ToList();
                        }
                        var temp2 = temp.Where(u => u.SiteID.Equals(siteId) && u.UnitID.Equals(unitId));
                        if (temp2.Count() <= (page-1) * recordsPerPage)
                        {
                            //nothing in the page, find next page
                            page = 1;
                            int theIndex =
                                    temp.IndexOf(
                                        temp.LastOrDefault(u => u.SiteID.Equals(siteId) && u.UnitID.Equals(unitId)));
                            if (string.IsNullOrEmpty(refreshMethod) || Tools.RefreshMethodList.Contains(refreshMethod))
                            {
                                refreshMethod = Tools.REFRESH_METHOD_NO;
                            }
                            else if (refreshMethod.Equals(Tools.REFRESH_METHOD_CURRENT_SITE))
                            {
                                //get next unit in the site
                                
                                if (theIndex < temp.Count - 1)
                                {
                                    //current unit is not the last unit
                                    if (temp[theIndex + 1].SiteID.Equals(siteId))
                                    {
                                        //next unit is the same site
                                        unitId = (temp[theIndex + 1]).UnitID;
                                    }
                                    else
                                    {
                                        //first unit in the site
                                        unitId = temp.FirstOrDefault(u => u.SiteID.Equals(siteId)).UnitID;
                                    }
                                }
                                else
                                {
                                    //first unit in the site
                                    unitId = temp.FirstOrDefault(u => u.SiteID.Equals(siteId)).UnitID;
                                }
                            }
                            else if (refreshMethod.Equals(Tools.REFRESH_METHOD_ALL))
                            {
                                if (theIndex < temp.Count - 1)
                                {
                                    siteId = temp[theIndex + 1].SiteID;
                                    unitId = temp[theIndex + 1].UnitID;
                                }
                                else
                                {
                                    siteId = temp.FirstOrDefault().SiteID;
                                    unitId = temp.FirstOrDefault().UnitID;
                                }
                            }
                            
                        }

                        result.AddRange(temp.Where(u=>u.SiteID.Equals(siteId) && u.UnitID.Equals(unitId)).Skip((page-1)*recordsPerPage).Take(recordsPerPage));
                    }

                }

            }
            return result;
        }





    }
}